package gui;
import gfx.Drawable;
import gfx.Tickable;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;

import modes.Mode.Modes;

import core.Main;
import core.Vector2;

/**
 * The main class to handle GUI-related Objects and the menu.
 * @author nick-luca.frank
 *
 */
public class GUI implements Drawable, Tickable {
	private boolean drawMenu;
	
	private Image menuBG;
	
	private int menuState; //id of the submenu
	private int usedSlots[]; //number of used slots in a menu state(MenuObjects);index is the menu-state
	private MenuObj menu[][]; //menu[submenu][slot]
	private List<Integer> menuHistory; //saves the the states in which the menu was when going into another state
	private List<Integer> positionHistory; //saves the previous cursor positions
	private int menuHistoryCounter; //equal to the size of menuHistory - 1 but needed later(for a cursor-position-history)
	
	public static Font font = new Font(Font.SERIF, Font.TRUETYPE_FONT, 64); //new Font with the size of  64p
	public static Font ddFont = new Font(Font.SERIF, Font.TRUETYPE_FONT, 12);
	private MenuCursor menuCursor;
	
	public GUI(){
		//add GUI as Drawable and Tickable
		Main.addDrawable(this);
		Main.addTickable(this);
		//don't draw the menu by default
		drawMenu = false;
		//menu-background
		menuBG = Main.imageLoader.load("/gui/MenuBG.png");
		
		menuState = 0;
		usedSlots = new int[14];
		menu = new MenuObj[14][7]; // the size of 7 was chosen through the size of the menu-background divided by the font-size
		menuHistory = new ArrayList<>();
		menuHistory.add(0);
		menuHistoryCounter = 0;
		positionHistory = new ArrayList<>();
		
		initMenus();
		
		menuCursor = new MenuCursor();
	}
	/**
	 * Adds a new MenuObject.
	 * @param subMenu the submenu to add it to
	 * @param text the text
	 * @param triggeredMenu the sub-menu that it calls when activated
	 */
	public void addToMenu(int subMenu, String text, int triggeredMenu){
		if(subMenu >= 0 && subMenu <= 14 && usedSlots[subMenu] < 9){
			menu[subMenu][usedSlots[subMenu]] = new MenuObj(usedSlots[subMenu], text, triggeredMenu);
			usedSlots[subMenu]++;
		}
	}
	/**
	 * Initializes the MenuObjects
	 */
	public void initMenus(){
		//--------------------------------------------------//
		this.addToMenu(0, "SOUND", 1);
		
		this.addToMenu(1, "tankfire", 1);
		this.addToMenu(1, "engine1", 1);
		this.addToMenu(1, "engine2", 1);
		this.addToMenu(1, "crash", 1);
		this.addToMenu(1, "wtfboom", 1);
		this.addToMenu(0, "Mode", 2);
		this.addToMenu(2, "Free Roam", 2);
		this.addToMenu(2, "Capture the Flag", 2);
		this.addToMenu(2, "Find the Path", 2);
		//--------------------------------------------------//
	}
	
	/**
	 * Checks if a MenuObject got triggered and reacts to it.
	 */
	public void procTriggeredMenuObjects(){
		if (menu[1][0].gotTriggered()){
			Main.soundManager.play(0);
		}
		if (menu[1][1].gotTriggered()){
			Main.soundManager.play(1);
		}
		if (menu[1][2].gotTriggered()){
			Main.soundManager.play(2);
		}
		if (menu[1][3].gotTriggered()){
			Main.soundManager.play(3);
		}
		if (menu[1][4].gotTriggered()){
			Main.soundManager.play(4);
		}
		if (menu[2][0].gotTriggered()) {
			Main.mode.setMode(Modes.FREE_ROAM);
		}
		if (menu[2][1].gotTriggered()) {
			Main.mode.setMode(Modes.CAPTURE_THE_FLAG);
		}
		if (menu[2][2].gotTriggered()) {
			Main.mode.setMode(Modes.FIND_THE_PATH);
		}
	}
	
	/**
	 * Checks key-presses and calls the procTrigerredMenuObjects method.
	 */
	@Override
	public void tick() {
		while(!Main.guiKeyListener.isQueueEmpty()){
			int key = Main.guiKeyListener.getQueuedKey();
			if(drawMenu){
				if(key == KeyEvent.VK_NUMPAD2){
					menuCursor.down(usedSlots[menuState]);
				}else if(key == KeyEvent.VK_NUMPAD5){
					menuCursor.up();
				}else if(key == KeyEvent.VK_NUMPAD3){
					int prevState = menuState;
					menuState = menu[menuState][menuCursor.getPosition()].trigger();
					
					if (prevState != menuState) {
						positionHistory.add(menuCursor.getPosition());
						menuCursor.reset();
						if(prevState != 0){
							menuHistory.add(menuState);
							menuHistoryCounter++;
						}
					}
				}else if(key == KeyEvent.VK_NUMPAD1){
					menuState = menuHistory.get(menuHistoryCounter);
					if(menuHistory.size() > 1){
						menuHistory.remove(menuHistoryCounter);
						menuHistoryCounter--;
					}
					if(positionHistory.size() > 0){
						menuCursor.setPosition(positionHistory.get(positionHistory.size() - 1));
						positionHistory.remove(positionHistory.size() - 1);
					}
				}
			}
			if (key == KeyEvent.VK_ENTER) {
				drawMenu = !drawMenu;
				menuCursor.reset();
			}
		}
		procTriggeredMenuObjects();
	}
	/**
	 * Renders the menu-background image and calls the render methods of every MenuObject.
	 */
	@Override
	public void render(Graphics g) {
		if(drawMenu){
			g.drawImage(menuBG, Main.WIDTH - 260, 4, 256, 512, null);
			for(int i = 0;i < usedSlots[menuState];i++){
				menu[menuState][i].render(g);
			}
			menuCursor.render(g);
		}
	}
	/**
	 * unused.
	 */
	@Override
	public boolean removed() {
		return false;
	}
	
	/**
	 * unused.
	 */
	@Override
	public Vector2 getPos() {
		return null;
	}

	/**
	 * unused.
	 */
	@Override
	public Color getColor() {
		return null;
	}

	/**
	 * unused.
	 */
	@Override
	public Vector2 getSize() {
		return null;
	}
	public int getID() {
		return 0;
	}
}